package pacBioSimple;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;


import tools.kmer.KmerSet_binary;


public class SlideAndMaskGenome {

	String genomeFileName =null;
	KmerSet_binary kmerDB = null;
	String genome_Masked=null;
	Double maskedVal=null;
	Map<String,Pair<Double, Double>>genomeMasked=null;
	
	
	public SlideAndMaskGenome(String genomeFilename, KmerSet_binary kmerDB,String genome_Masked)
	{
		this.genomeFileName=genomeFilename;
		this.kmerDB=kmerDB;
		this.genome_Masked=genome_Masked;
		this.genomeMasked = new HashMap<String, Pair<Double,Double>>();
	}
	
	public void doSlidingAndMasking()
	{
		try {
			BufferedReader br = new BufferedReader(new FileReader(genomeFileName));
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(genome_Masked)));
			PrintWriter pw2 = new PrintWriter(new BufferedWriter(new FileWriter(genome_Masked+"_stat")));
			StringBuilder chr = new StringBuilder();
			String chrName="";
			while(br.ready())
			{
				String line = br.readLine();
				line=line.trim();
				if(line.startsWith(">"))
				{
					// new chr
					//write chr
					if(chr.length()>0)
					{
						//before writing we have to slide and mask the genome
						//System.out.println(chr);
						StringBuilder masked_genome=slideAndMask(chr,chrName);
						pw = writeChr(masked_genome,chrName,pw);
					}
					chr = new StringBuilder();
					chrName=line;
				}
				else
				{
					chr.append(line);
				}
				
			}
			StringBuilder masked_genome=slideAndMask(chr,chrName);
			pw = writeChr(masked_genome,chrName,pw);
			pw2= writeStat(this.genomeMasked, pw2);
			
			pw.flush();
			pw2.flush();
			
			pw.close();
			pw2.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	private StringBuilder slideAndMask(StringBuilder chr,String chr_name)
	{
		StringBuilder masked_genome= new StringBuilder();
		int number_of_old_masked=0;
		int number_of_new_masked=0;
		int i=0;
		//System.out.println(kmerDB.getKmerSize());
		while(i<chr.length()-this.kmerDB.getKmerSize())
		{
			String fragment = chr.substring(i,i+this.kmerDB.getKmerSize());
			
			while(fragment.contains("N") || fragment.contains("n") )
			{
				masked_genome.append(chr.charAt(i));
				if(chr.charAt(i) == 'N' || chr.charAt(i) == 'n' )
				{
					++number_of_old_masked;
				}
				++i;
				
				if(i+this.kmerDB.getKmerSize()<=chr.length()-1)
				{
					fragment = chr.substring(i,i+this.kmerDB.getKmerSize());
				}
				else
				{
					fragment=null;
					break;
				}
			}
			if(fragment != null)
			{
				int kmerVal=MyUtil.checkKmerDistribution(fragment,this.kmerDB);
				
				if(kmerVal<=0)
				{
					//masked total fragment
					for(int j=0; j < fragment.length();++j)
					{
						masked_genome.append("N");
						if(j>0)
						++i;
					}
					
					number_of_new_masked+=this.kmerDB.getKmerSize();
				}
				else
				{
					masked_genome.append(chr.charAt(i));	
				}
				
				++i;
			}
			else
			{
				break;
			}
		}
		
		String endFragment = chr.substring(chr.length()-this.kmerDB.getKmerSize(),chr.length());
		if(endFragment.contains("N") || endFragment.contains("n") )
		{
			for(int j=0; j<endFragment.length();++j)
			{
				masked_genome.append(endFragment.charAt(j));
				if(endFragment.charAt(j) == 'N'||endFragment.charAt(j) == 'n')
				{
					++number_of_old_masked;
				}
			}
		}
		else
		{
			int kmerVal=MyUtil.checkKmerDistribution(endFragment,this.kmerDB);
			if(kmerVal<=0)
			{
				for(int j=0; j < endFragment.length();++j)
				{
					masked_genome.append("N");
				}
				number_of_new_masked+=this.kmerDB.getKmerSize();
			}
			else
			{
				for(int j=0; j < endFragment.length();++j)
				{
					masked_genome.append(endFragment.charAt(j));
				}
			}
		}
		genomeMasked.put(chr_name,new Pair<Double, Double>(((double)number_of_old_masked/chr.length()*100),((double)number_of_new_masked/chr.length()*100)) );
		return masked_genome;
	}
	
	private PrintWriter writeChr(StringBuilder chr, String chr_name,PrintWriter pw)
	{
		pw.println(chr_name);
		pw.println(chr);
		pw.flush();
		return pw;
	}

	private PrintWriter writeStat(Map<String, Pair<Double, Double>> stat,PrintWriter pw)
	{
		
		for(Map.Entry<String, Pair<Double,Double>>entry:stat.entrySet())
		{
			pw.println(entry.getKey()+"\t"+entry.getValue().getFirst()+"\t"+entry.getValue().getSecond());
		}
		pw.flush();
		return pw;
	}
	


//	private int checkKmerDistribution(String kmer)
//	{
//		//System.out.print(kmer+ " kmer check\n");
//		if(kmer.equals(""))
//		{
//			return 0;
//		}
//		kmer=kmer.toUpperCase();
//		String kmerToUse = kmerFunctions.kmerToUse(kmer);
//		BitSet bS = kmerDB.getUtils().stringToBitSet(kmerToUse);
//		//BitSet bS = ks.getUtils().stringToBitSet(kmerFunctions.kmerToUse(kmer.toString()));
//		if(kmerDB.exists(kmerToUse))
//		{
//			return(kmerDB.getNumber(bS));
//		}
//		else
//		{
//			return 0;
//		}
//	}

}